package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BusAppointment;
import cn.wolfcode.business.domain.BusStatement;
import cn.wolfcode.business.mapper.BusStatementMapper;
import cn.wolfcode.business.service.IBusAppointmentService;
import cn.wolfcode.business.service.IBusStatementService;
import cn.wolfcode.business.util.DateUtil;
import cn.wolfcode.business.util.RegexUtils;
import cn.wolfcode.business.util.VehiclePlateNoUtil;
import cn.wolfcode.common.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 结算单Service业务层处理
 * 
 * @author wolfcode
 * @date 2025-05-10
 */
@Service
public class BusStatementServiceImpl implements IBusStatementService 
{
    @Autowired
    private BusStatementMapper busStatementMapper;
    @Autowired
    private IBusAppointmentService appointmentService;

    /**
     * 查询结算单
     * 
     * @param id 结算单主键
     * @return 结算单
     */
    @Override
    public BusStatement selectBusStatementById(Long id)
    {
        return busStatementMapper.selectBusStatementById(id);
    }

    /**
     * 查询结算单列表
     * 
     * @param busStatement 结算单
     * @return 结算单
     */
    @Override
    public List<BusStatement> selectBusStatementList(BusStatement busStatement)
    {
        // 获取到结束时间 endActualArrivalTime。
        Map<String, Object> params = busStatement.getParams();
        String endActualArrivalTime = (String) params.get("endActualArrivalTime");
        // 将 String 类型的 endActualArrivalTime 转换为 DATE 类型
        Date date = DateUtil.parseDate(endActualArrivalTime, "yyyy-MM-dd");
        // 再将转后的数据 +1 天 -1 秒。
        Date endTime = DateUtil.getEndTime(date); // yyyy-MM-dd HH:mm:ss 时间转换(时分秒)
        // 再将该 Date 类型转换回 String 类型

        String endDate = DateUtil.parseString(endTime, "yyyy-MM-dd HH:mm:ss"); //  yyyy-MM-dd HH:mm:ss
        // 再赋值回当前对象。
        params.put("endActualArrivalTime",endDate);
        // 设置 is_delete 为 IS_NOT_DELETE 查询有效用户
        busStatement.setIsDelete(BusStatement.IS_NOT_DELETE);
        return busStatementMapper.selectBusStatementList(busStatement);
    }

    /**
     * 新增结算单
     * 
     * @param busStatement 结算单
     * @return 结果
     */
    @Override
    public int insertBusStatement(BusStatement busStatement)
    {
        // 参数合法性验证
        if(busStatement == null){
            throw new RuntimeException("非法参数");
        }
        // 前天验证的后台都要验证一次
        if(busStatement.getCustomerName() == null || busStatement.getCustomerPhone() == null
            || busStatement.getActualArrivalTime() == null || busStatement.getLicensePlate() == null
            || busStatement.getCarSeries() == null || busStatement.getServiceType() == null){
            throw new RuntimeException("非法参数");
        }
        // 手机号码验证
        if (!RegexUtils.isPhoneLegal(busStatement.getCustomerPhone())) {
            throw new RuntimeException("手机号码格式有误");
        }
        // 车牌号码验证
        VehiclePlateNoUtil.VehiclePlateNoEnum vehiclePlateNo =
                VehiclePlateNoUtil.getVehiclePlateNo(busStatement.getLicensePlate());
        if(vehiclePlateNo == null){
            throw new RuntimeException("车牌号码格式有误");
        }
        // 到店时间 < 当前系统时间
        if(!(busStatement.getActualArrivalTime().before(DateUtils.getNowDate()))){
            throw new RuntimeException("到店时间应再当前系统时间之前");
        }
        // 安全验证。将状态设置为消费中
        busStatement.setStatus(BusStatement.STATUS_CONSUME);
        // 安全验证。is_delete = 0
        busStatement.setIsDelete(BusStatement.IS_NOT_DELETE);
        busStatement.setCreateTime(DateUtils.getNowDate());
        return busStatementMapper.insertBusStatement(busStatement);
    }

    /**
     * 修改结算单
     * 
     * @param busStatement 结算单
     * @return 结果
     */
    @Override
    public int updateBusStatement(BusStatement busStatement)
    {
        // 参数合法性验证
        if(busStatement == null){
            throw new RuntimeException("非法参数");
        }
        // 前天验证的后台都要验证一次
        if(busStatement.getCustomerName() == null || busStatement.getCustomerPhone() == null
                || busStatement.getActualArrivalTime() == null || busStatement.getLicensePlate() == null
                || busStatement.getCarSeries() == null || busStatement.getServiceType() == null){
            throw new RuntimeException("非法参数");
        }
        // 手机号码验证
        if (!RegexUtils.isPhoneLegal(busStatement.getCustomerPhone())) {
            throw new RuntimeException("手机号码格式有误");
        }
        // 车牌号码验证
        VehiclePlateNoUtil.VehiclePlateNoEnum vehiclePlateNo =
                VehiclePlateNoUtil.getVehiclePlateNo(busStatement.getLicensePlate());
        if(vehiclePlateNo == null){
            throw new RuntimeException("车牌号码格式有误");
        }
        // 到店时间 < 当前系统时间
        if(!(busStatement.getActualArrivalTime().before(DateUtils.getNowDate()))){
            throw new RuntimeException("到店时间应再当前系统时间之前");
        }
        // 验证必须是消费中才可以进行编辑操作。
        // （有没有可能别人通过特殊方式将已支付状态结算单，使用特殊方式修改为未支付传递进来）。
        // 验证时，我们不能用传递进来的对象进行验证
        // 我们需要根据当前对象 id 查询出原始对象（原始对象是数据库中存在的。状态再当前页面是不允许修改的）
        // 我们需要根据查询出来的原始对象的状态进行判定。
        BusStatement oldObj = this.selectBusStatementById(busStatement.getId());
        if(BusStatement.STATUS_PAID.equals(oldObj.getStatus())){
            throw new RuntimeException("必须是消费中的结算单才可以进行编辑操作");
        }
        // 防止而已攻击
        busStatement.setStatus(BusStatement.STATUS_CONSUME);
        // 安全验证，必须是有效用户才可以进行编辑
        if(BusStatement.IS_DELETE.equals(oldObj.getIsDelete())){
            throw new RuntimeException("无效用户禁止编辑");
        }
        return busStatementMapper.updateBusStatement(busStatement);
    }

    /**
     * 批量删除结算单
     * 
     * @param ids 需要删除的结算单主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteBusStatementByIds(Long[] ids)
    {
        // 参数合法性验证
        if(ids == null || ids.length != 1){
            throw new RuntimeException("非法参数");
        }
        // 获取我们的结算单 id
        Long id = ids[0];
        // 根据 id 查询结算的那对象
        BusStatement statement = this.selectBusStatementById(id);
        if(statement == null){
            throw new RuntimeException("非法参数");
        }
        // 状态必须是消费中的结算单才可以进行删除操作
        if(BusStatement.STATUS_PAID.equals(statement.getStatus())){
            throw new RuntimeException("已支付的结算单禁止删除");
        }
        // 判断当前结算单是否关联了预约单。
        if(statement.getAppointmentId() != null){
            // 若关联了预约单我们还需要更改预约单状态（将其状态回退到已到店）。
            appointmentService.updateStatusById(statement.getAppointmentId(), BusAppointment.STATUS_ARRIVED);
        }
        // 删除结算单
        return busStatementMapper.deleteIsDelete(id,BusStatement.IS_DELETE);
    }

    /**
     * 删除结算单信息
     * 
     * @param id 结算单主键
     * @return 结果
     */
    @Override
    public int deleteBusStatementById(Long id)
    {
        return busStatementMapper.deleteBusStatementById(id);
    }

    /**
     * 根据结算单 id 更新结算单总价格、总数量、折扣价
     */
    @Override
    public int updateAmount(Long statementId, BigDecimal totalAmount, BigDecimal totalQuantity, BigDecimal discountAmount) {
        return busStatementMapper.updateAmount(statementId, totalAmount, totalQuantity, discountAmount);
    }

    /**
     * 根据 id 更新 收款人、收款时间、状态
     */
    @Override
    public int updatePayStatusAndPayTimeAndPayId(Long statementId, Long payId, Date date, Integer statusPaid) {
        return busStatementMapper.updatePayStatusAndPayTimeAndPayId(statementId, payId, date, statusPaid);
    }

    /**
     * 根据预约单 ID 查询结算单
     */
    @Override
    public BusStatement queryStatementByAppointmentId(Long appointmentId) {
        return busStatementMapper.queryStatementByAppointmentId(appointmentId);
    }

    /**
     * 根据结算单 ID 修改结算单软删除状态
     */
    @Override
    public void changeIsDeleteStatus(Long id, Integer isNotDelete) {
        busStatementMapper.changeIsDeleteStatus(id, isNotDelete);
    }
}
